﻿#ifndef GY_CPUCOUNTERTIMER_H
#define GY_CPUCOUNTERTIMER_H
#include<QObject>
#include<QDate>
#include<QMutex>
#include"GY_ControlLibrary_global.h"
#include <windows.h>
#include <QThread>
#include <QSemaphore>

typedef LARGE_INTEGER *PLARGE_INTEGER;
//一天微妙数
#define ONE_DATE_MICROSECONDCOUNT  86400000000

/**
 * @brief The TimerMode enum  计时器模式
 */
enum TimerMode
{
    //!主动计时(开启线程计时)
    InitiativeTimer,
    //!被动计时(只会在调用函数的时候获取)
    PassivityTimer
};

/**
 * @brief The GY_CPUCounterTimer class
 * 基于CPU计数器的计时器类
 */
class GY_CONTROLLIBRARY_EXPORT GY_CPUCounterTimer : public QObject
{
    Q_OBJECT
public:
    explicit GY_CPUCounterTimer(QObject *parent = nullptr);
    ~GY_CPUCounterTimer();
    /**
     * @brief getCurrentTime 获取当前时间
     * @return 返回当前计时时间
     */
    quint64 getCurrentTime();
    /**
     * @brief setCurrentTime 设置当前时间
     * @param time 当前时间
     */
    void setCurrentTime(const quint64 time);
    /**
     * @brief getCurrentDate  获取当前日期
     * @return 返回日期
     */
    QDate getCurrentDate();
    /**
     * @brief setCurrentDate 设置当前日期
     * @param date 日期
     */
    void setCurrentDate(const QDate & date);
    /**
     * @brief startTimer 开始计时：被动模式
     * @param timeInter 计时器间隔:us
     */
    void startTimer(const quint32 timeInter);
    /**
     * @brief startTimer 开始计时：主动模式
     */
    void startTimer();
    /**
     * @brief stopTimer
     * 停止计时器
     */
    void stopTimer();
    /**
     * @brief setTimerSpeed  设置计时器速率
     * @param timeSpeed 计时速率
     */
    void setTimerSpeed(const double timeSpeed);

    /**
     * @brief uintToHourMinSec uint转换为时分秒
     * @param time uint时间
     * @return 时分秒格式的时间
     */
    static QString uintToHourMinSec(quint32 time);

private:
    //!计数器频率
    LARGE_INTEGER m_CounterFrequency;
    //!计数器初始次数
    LARGE_INTEGER m_LastCount;
    //!计数器当前次数
    LARGE_INTEGER m_CurrentCount;
    //!初始时间(单位:us)
    quint64 m_StartTime;
    //!当前时间(单位:us)
    quint64 m_CurrentTime;
    //!当前日期
    QDate m_CurrentDate;
    //!间隔时间(单位:us)
    quint32 m_TimeInter;
    //!上一次的超时值
    quint64 m_LastTimeOutTime;
    //!计时速率
    double m_TimeSpeed;
    //!时间互斥锁
    QMutex m_TimeMutex;
    //!日期互斥锁
    QMutex m_DateMutex;
    //!线程锁
    QMutex m_ThreadMutex;
    //!计时器运行模式
    TimerMode m_TimerMode;
    //!计时运行
    bool isRuning;
    //!设备是否支持CPU计数器
    bool devIsOk;
    //!线程对象
    QThread* m_pThread;

#ifdef WIN32
    //!windows使用的计数器函数
    typedef bool (*QueryPerformanceCounter)(PLARGE_INTEGER pCount);
    typedef bool (*QueryPerformanceFrequency)(PLARGE_INTEGER pFrequency);
    //!获取计数器计数
    QueryPerformanceCounter m_Fun_QueryPerformanceCounter;
    //!获取计数器频率
    QueryPerformanceFrequency m_Fun_QueryPerformanceFrequency;
#endif

private:
    /**
     * @brief timeOutEvent 超时事件
     */
    void timeOutEvent();

    /**
     * @brief timeConvertDate 时间日期转换
     * @param date 日期
     * @param time 时间
     */
    void timeConvertDate(QDate date, qint64 time);

signals:
    /**
     * @brief timeOutSiganl 定时器信号
     * @param currentDate 当前日期
     * @param currentTime 当前时间
     */
    void timeOutSiganl(const QDate currentDate,const quint64 currentTime);
};

#endif // GY_CPUCOUNTERTIMER_H
